package com.deepalhome.deepalclub.adb

import android.widget.EditText
import com.blankj.utilcode.util.ThreadUtils
import com.blankj.utilcode.util.ThreadUtils.Task
import com.blankj.utilcode.util.ToastUtils
import io.github.muntashirakon.adb.AdbStream
import io.github.muntashirakon.adb.LocalServices
import java.nio.charset.StandardCharsets
import java.util.concurrent.TimeUnit

object AdbUtil {
    private var onConnectionChangedListener: ((Boolean) -> Unit)? = null
    private var isConnected = false
    private var adbStream: AdbStream? = null
    private val checkConnectionTask = object : Task<Boolean>() {
        override fun doInBackground() = AdbConnectionManager.isConnected

        override fun onCancel() {

        }

        override fun onFail(t: Throwable?) {
            ToastUtils.showLong(t?.message)
        }

        override fun onSuccess(result: Boolean) {
            if (result == isConnected) {
                return
            }
            isConnected = result
            onConnectionChangedListener?.invoke(result)
        }
    }

    init {
        ThreadUtils.executeBySingleAtFixRate(checkConnectionTask, 1, TimeUnit.SECONDS)
    }

    fun setOnConnectionChangedListener(listener: (Boolean) -> Unit) {
        this.onConnectionChangedListener = listener
        listener.invoke(isConnected)
    }

    fun connect(host: String, portEt: EditText, callback: (Boolean) -> Unit) {
        ThreadUtils.executeBySingle(object : Task<String>() {
            override fun doInBackground(): String {
                val port = portEt.text.toString()
                return try {
                    if (AdbConnectionManager.connect(host, port.toInt())) {
                        "连接成功"
                    } else {
                        "连接失败"
                    }
                } catch (e: Exception) {
                    if (e is NumberFormatException) {
                        return "请输入正确的端口"
                    }
                    when (e.message) {
                        "Connection failed" -> "连接失败，请检查后网络和输入后重试"
                        "ADB pairing is required." -> "请先完成配对操作"
                        else -> e.message ?: "连接错误，请检查后网络和输入后重试"
                    }
                }
            }

            override fun onCancel() {
            }

            override fun onFail(t: Throwable?) {
            }

            override fun onSuccess(result: String) {
                ToastUtils.showLong(result)
                ThreadUtils.runOnUiThread { callback.invoke(AdbConnectionManager.isConnected) }
            }
        })
    }

    fun disableHealthManager() {
        execute("adb shell pm disable-user --user 0 com.mega.healthmanager")
    }

    fun grantDeepalHome() {
        execute("pm grant com.deepalhome.launcher android.permission.READ_LOGS & am force-stop com.deepalhome.launcher & am start -n com.deepalhome.launcher/com.deepalhome.launcher.MainActivity")
    }

    fun repairAppStore() {
        execute("pm clear com.mega.appstore")
    }

    private fun execute(command: String) {
        ThreadUtils.executeBySingle(object : Task<String>() {
            override fun doInBackground(): String {
                return try {
                    if (adbStream == null || adbStream?.isClosed == true) {
                        adbStream?.close()
                        adbStream = AdbConnectionManager.openStream(LocalServices.SHELL)
                    }
                    adbStream?.openOutputStream()?.use { os ->
                        os.write(
                            String.format("%1\$s\n", command).toByteArray(StandardCharsets.UTF_8)
                        )
                        os.flush()
                        os.write("\n".toByteArray(StandardCharsets.UTF_8))
                    }
                    "操作成功"
                } catch (e: java.lang.Exception) {
                    e.message ?: "未知错误"
                }
            }

            override fun onCancel() {
            }

            override fun onFail(t: Throwable?) {
            }

            override fun onSuccess(result: String) {
                ToastUtils.showLong(result)
            }
        })
    }

    fun destroy() {
        ThreadUtils.cancel(checkConnectionTask)
    }
}